from .utils import singleton
from typing import Literal
import threading


@singleton
class PropSemaphore:

    _initialized = False

    def __init__(self):
        if not self._initialized:
            self.execProp = threading.Semaphore(0)
            self.finishProp = threading.Semaphore(0)
            self.exit = threading.Event()
            # Signal for hooks
            self.before_monkey = threading.Semaphore(0)
            self.after_monkey = threading.Semaphore(0)
            self.before_monkey_done = threading.Semaphore(0)
            self.after_monkey_done = threading.Semaphore(0)


@singleton
class PropExecutionInfo:
    _initialized = False

    def __init__(self):
        if not self._initialized:
            self.propName = None
            self.state: Literal["Ongoing", "Completed"] = None
            self.api_name = None
            self.args = None

    def clear(self):
        self.propName = None
        self.state = None
        self.api_name = None
        self.args = None

    def setPropStepInfo(self, propName, state: Literal["Ongoing", "Completed"]):
        self.propName = propName
        self.state = state

    def __repr__(self):
        return repr({
            "propName": self.propName,
            "state": self.state,
            "apiName": self.api_name,
            "args": self.args,
        })


@singleton
class PropertyExecManager:
    """
    执行控制器，主要实现对控制权的交换，核心是两个 Event 事件:
    monkey_runing 和 kea2_runing

    初始化时 为 monkey_runing 置位， kea2_runing 没有置位
    """

    _initialized = False
    propExecInfo: PropExecutionInfo

    def __init__(self):
        if not self._initialized:
            self.kea2_runing = threading.Event()
            self.monkey_runing = threading.Event()
            self.monkey_runing.set()
            self.exit_event = threading.Event()
            self.propExecInfo = PropExecutionInfo()
        self._initialized = True

    def switch_controller(self, target:Literal["monkey", "kea2"]):
        """
        交换控制权
        """
        if target == "kea2":
            if self.monkey_runing.is_set():
                print("[Kea2] Controller is monkey, switching to Kea2")
            self.monkey_runing.clear()
            self.kea2_runing.set()
        else:
            if self.kea2_runing.is_set():
                print("[Kea2] Controller is Kea2, switching to Monkey")
            self.kea2_runing.clear()
            self.monkey_runing.set()

    def exit(self):
        self.kea2_runing.set()
        self.exit_event.set()